#include <QTreeWidgetItem>
#include <QModelIndex>
#include <QTableView>

#include "bkptsmanager.h"
#include "editortabwidget.h"
#include "meditor.h"
#include "mainwindow.h"

BkptsManager::BkptsManager (MainWindow *p)
    :QDialog (p)
{
    setupUi(this);

    m_mainWindow = p;
    m_editorTab = p->getEditorTab();
    m_bkptsModel = new BreakpointsModel(this);

    bkptsView->setModel(m_bkptsModel);
    bkptsView->setColumnWidth(0, 20);
    bkptsView->setColumnWidth(1, 50);
    bkptsView->header()->setSectionsClickable(false);
    bkptsView->header()->setSectionResizeMode(QHeaderView::Fixed);

    connect (allButton, SIGNAL(clicked()),
             m_bkptsModel, SLOT(selectAll()));
    connect (invertButton, SIGNAL(clicked()),
             m_bkptsModel, SLOT(selectInvert()));
    connect (deleteButton, SIGNAL(clicked()),
             m_bkptsModel, SLOT(deleteSelected()));
    connect (m_bkptsModel, SIGNAL(deleteBkpt(QString,int)),
             m_mainWindow, SLOT(slotToggleBreakpoint(QString,int)));
    connect (m_bkptsModel, SIGNAL(condChanged(QString,int,QString)),
             m_mainWindow, SLOT(toConditional(QString,int,QString)));

    for (int i = 0; i < m_editorTab->count(); i++) {
        QString f = m_editorTab->editor(i)->getFileName();
        comboBox->insertItem(i, f.section('/', -1));
        comboBox->setItemData(i, f, Qt::ToolTipRole);
    }
    comboBox->setCurrentIndex(m_editorTab->currentIndex());

    selectFile(m_editorTab->currentIndex());
    connect (comboBox, SIGNAL(currentIndexChanged(int)),
             this, SLOT(selectFile(int)));
}

void BkptsManager::selectFile(int i)
{
    QString f = comboBox->itemData(i, Qt::ToolTipRole).toString();
    QMap<int, QString> m;
    m_editorTab->editor(f)->getAllBreakpoints(m);
    m_bkptsModel->setBreakpoints(m, f);
}

int BreakpointsModel::rowCount(const QModelIndex &) const
{
    return breakpoints.count();
}

int BreakpointsModel::columnCount(const QModelIndex &) const
{
    return ColumnCount;
}

QVariant BreakpointsModel::data(const QModelIndex &i, int role) const
{
    if (!i.isValid())
        return QVariant();
    if (i.row() >= breakpoints.size() || i.column() >= ColumnCount)
        return QVariant();
    if (role == Qt::DisplayRole) {
        if (i.column() == LineColumn) {
            return QString::number(breakpoints.keys().at(i.row()))+" ";
        }
        if (i.column() == ConditionColumn) {
            return " "+breakpoints.values().at(i.row());

        }
    } else if ((role == Qt::EditRole) && (i.column() == ConditionColumn)) {
        return breakpoints.values().at(i.row());
    } else if ((role == Qt::CheckStateRole) && (i.column() == CheckColumn)) {
        return (checkState.value(index(i.row(), LineColumn).data().toInt()) == Qt::Checked) ?
                    Qt::Checked : Qt::Unchecked;
    } else if (role == Qt::TextAlignmentRole) {
        if (i.column() == LineColumn) {
            return 0x82;
        } else if (i.column() == ConditionColumn) {
            return 0x81;
        }
    } else
        return QVariant();
    return QVariant();
}

QVariant BreakpointsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole) {
        return QVariant();
    }
    if (orientation == Qt::Horizontal) {
        if (section == LineColumn)
            return QString(tr("Line"));
        else if (section == ConditionColumn)
            return QString(tr("Condition"));
    } else
        return QVariant();
    return QVariant();
}

Qt::ItemFlags BreakpointsModel::flags(const QModelIndex &index) const
{
    if (index.column() == ConditionColumn) {
        return  Qt::ItemIsEditable | Qt::ItemIsEnabled ;
    } else if (index.column() == CheckColumn) {
        return  Qt::ItemIsUserCheckable | Qt::ItemIsEnabled ;
    } else {
        return  Qt::ItemIsEnabled ;
    }
}

bool BreakpointsModel::setData(const QModelIndex &i, const QVariant &v, int r)
{
    if (r == Qt::EditRole) {
        int l = index(i.row(), LineColumn).data().toInt();
        QString c = v.toString();
        qDebug((l + c).toUtf8().constData());
        emit condChanged(file, l, c);
        emit dataChanged(i, i);
        breakpoints.insert(l, c);
    } else if (r == Qt::CheckStateRole) {
        int l = index(i.row(), LineColumn).data().toInt();
        if (v == Qt::Checked)
            checkState.insert(l, Qt::Checked);
        else
            checkState.insert(l, Qt::Unchecked);
    }
    return true;
}

void BreakpointsModel::setBreakpoints(const QMap<int, QString> map, QString f) {
    emit beginResetModel();
    breakpoints = map;
    file = f;
    checkState.clear();
    for (QMap<int, QString>::ConstIterator i = breakpoints.begin();
         i != breakpoints.end(); i++) {
        checkState.insert(i.key(), Qt::Unchecked);
    }
    emit endResetModel();
}

void BreakpointsModel::selectAll()
{
    for (QMap<int, Qt::CheckState>::Iterator i = checkState.begin();
        i != checkState.end(); i++) {
        i.value() = Qt::Checked;
    }
    emit dataChanged(index(0,0), index(breakpoints.size(), ColumnCount));
}

void BreakpointsModel::selectInvert()
{
    for (QMap<int, Qt::CheckState>::Iterator i = checkState.begin();
        i != checkState.end(); i++) {
        if (i.value() == Qt::Checked)
            i.value() = Qt::Unchecked;
        else
            i.value() = Qt::Checked;
    }
    emit dataChanged(index(0,0), index(breakpoints.size(), ColumnCount));
}

void BreakpointsModel::deleteSelected()
{
    int s = breakpoints.size();
    QMap<int, Qt::CheckState>::Iterator i = checkState.begin();
    while (i != checkState.end()) {
        if (i.value() == Qt::Checked) {
            int l = i.key();
            breakpoints.remove(l);
            i = checkState.erase(i);
            emit deleteBkpt(file, l);
        } else
            i++;
    }
    emit dataChanged(index(0,0), index(s, ColumnCount));
}
